﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;

namespace FACUI.BasicClass
{
    public enum OperType
    {
        赋值,
        List添加,
        List删除,
        Dict添加,
        Dict删除,
        分割符
    }
    /***********************************************************************************************/
    public class OperElement
    {
        public string desc;
        public object newValue;
        public object oldValue;
        public ClassBase operObject;
        public OperType operType;
        public static int sid = 0;

        public OperElement(string desc)
        {
            this.operType = OperType.赋值;
            this.oldValue = null;
            this.newValue = sid++;
            this.operObject = null;
            this.desc = desc;
        }

        public OperElement(ClassBase operObject, object newValue)
        {
            this.operType = OperType.赋值;
            this.oldValue = operObject.value;
            this.newValue = newValue;
            this.operObject = operObject;
            this.desc = operObject.value.ToString() + ":from[" + this.oldValue.ToString() + "] to [" + newValue.ToString() + "]";
        }

        public OperElement(ClassBase operObject, object oldValue, object newValue)
        {
            this.operType = OperType.赋值;
            this.oldValue = oldValue;
            this.newValue = newValue;
            this.operObject = operObject;
            this.desc = operObject.value.ToString() + ":from[" + oldValue.ToString() + "] to [" + newValue.ToString() + "]";
        }

        public OperElement(OperType operType, ClassBase operObject, object oldValue, object newValue)
        {
            this.operType = OperType.赋值;
            this.operType = operType;
            this.oldValue = oldValue;
            this.newValue = newValue;
            this.operObject = operObject;
            this.desc = string.Concat(new object[] { operObject.value, ":from[", oldValue, "] to [", newValue, "]" });
        }
    }
    /****************************************************************/
    public class MapStack : Stack
    {
        public bool isModified = false;
        public bool needPush = true;
        private Stack<OperElement> reDoStack = new Stack<OperElement>();

        public override void Clear()
        {
            base.Clear();
        }

        public void doOper(OperElement oe, bool isUndo)
        {
            if (!this.isModified)
            {
                this.isModified = true;
            }
            if (isUndo)
            {
                if (oe.operType == OperType.赋值)
                {
                    oe.operObject.value = oe.oldValue;
                }
                else if (oe.operType == OperType.List删除)
                {
                    ((IList)oe.operObject.value).Insert((int)oe.oldValue, oe.newValue);
                }
                else if (oe.operType == OperType.List添加)
                {
                    ((IList)oe.operObject.value).Remove(oe.newValue);
                }
                else if (oe.operType == OperType.Dict删除)
                {
                    ((IDictionary)oe.operObject.value).Add(oe.oldValue, oe.newValue);
                }
                else if (oe.operType == OperType.Dict添加)
                {
                    ((IDictionary)oe.operObject.value).Remove(oe.oldValue);
                }
            }
            else if (oe.operType == OperType.赋值)
            {
                oe.operObject.value = oe.newValue;
            }
            else if (oe.operType == OperType.List删除)
            {
                ((IList)oe.operObject.value).RemoveAt((int)oe.oldValue);
            }
            else if (oe.operType == OperType.List添加)
            {
                ((IList)oe.operObject.value).Add(oe.newValue);
            }
            else if (oe.operType == OperType.Dict删除)
            {
                ((IDictionary)oe.operObject.value).Remove(oe.oldValue);
            }
            else if (oe.operType == OperType.Dict添加)
            {
                ((IDictionary)oe.operObject.value).Add(oe.oldValue, oe.newValue);
            }
        }

        public override bool Equals(object obj)
        {
            return base.Equals(obj);
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        public override object Peek()
        {
            return base.Peek();
        }

        public override object Pop()
        {
            return base.Pop();
        }

        public override void Push(object obj)
        {
            OperElement element = (OperElement)obj;
            if (this.reDoStack.Count > 0)
            {
                this.reDoStack.Clear();
            }
            if ((element.oldValue != element.newValue) && this.needPush)
            {
                if (!(this.isModified || (element.operObject == null)))
                {
                    this.isModified = true;
                }
                base.Push(element);
            }
        }

        public void Push(ClassBase operObject, object newValue)
        {
            this.Push(new OperElement(operObject, newValue));
        }

        public void Push(ClassBase operObject, object oldValue, object newValue)
        {
            this.Push(new OperElement(operObject, oldValue, newValue));
        }

        public void Push(OperType operType, ClassBase operObject, object oldValue, object newValue)
        {
            this.Push(new OperElement(operType, operObject, oldValue, newValue));
        }

        public OperElement ReDo()
        {
            OperElement element = null;
            int num = 0;
            try
            {
                while (this.reDoStack.Count > 0)
                {
                    element = this.reDoStack.Peek();
                    if (element.operObject != null)
                    {
                        base.Push(element);
                        this.ToString();
                        this.doOper(element, false);
                        this.reDoStack.Pop();
                    }
                    else
                    {
                        num++;
                        if (num >= 2)
                        {
                            return null;
                        }
                        base.Push(element);
                        this.reDoStack.Pop();
                    }
                }
                return null;
            }
            catch (Exception exception)
            {
                MessageBox.Show(exception.ToString());
            }
            return null;
        }

        public override object[] ToArray()
        {
            return base.ToArray();
        }

        public OperElement UnDo()
        {
            OperElement item = null;
            try
            {
                bool flag;
                goto Label_004E;
            Label_0006:
                if (this.Count > 0)
                {
                    item = (OperElement)base.Peek();
                    if (item.operObject == null)
                    {
                        item = (OperElement)base.Pop();
                        goto Label_004E;
                    }
                }
                goto Label_00F3;
            Label_004E:
                flag = true;
                goto Label_0006;
            Label_0057:
                if (this.Count <= 0)
                {
                    return null;
                }
                item = (OperElement)base.Pop();
                this.reDoStack.Push(item);
                if (item.operObject != null)
                {
                    goto Label_00E9;
                }
                goto Label_00E1;
            Label_0099:
                if (this.Count > 0)
                {
                    item = (OperElement)base.Peek();
                    if (item.operObject == null)
                    {
                        item = (OperElement)base.Pop();
                        goto Label_00E1;
                    }
                }
                return null;
            Label_00E1:
                flag = true;
                goto Label_0099;
            Label_00E9:
                this.doOper(item, true);
            Label_00F3:
                flag = true;
                goto Label_0057;
            }
            catch (Exception exception)
            {
                MessageBox.Show(exception.ToString());
            }
            return null;
        }

        public override int Count
        {
            get
            {
                return base.Count;
            }
        }
    }
}

